package httpclient

import (
	"bytes"
	"context"
	"io"
	"net/http"
	"net/url"
	"time"
)

var client = http.Client{}
var hc *Httpclient = NewHttpclient()

func GetHttpclient() *Httpclient {
	return hc
}

type Httpclient struct {
	url         string            // 请求地址
	method      string            // 请求方法
	timeout     time.Duration     // 请求超时
	queryParams url.Values        // post 参数
	headers     map[string]string // 请求头
	body        []byte            // 请求体
	ctx         context.Context   // context
}

func NewHttpclient() *Httpclient {
	return &Httpclient{}
}

func (c *Httpclient) Url(url string) *Httpclient {
	c.url = url
	return c
}

func (c *Httpclient) Method(method string) *Httpclient {
	c.method = method
	return c
}

func (c *Httpclient) Body(body []byte) *Httpclient {
	c.body = body
	return c
}

func (c *Httpclient) QueryParams(queryParams url.Values) *Httpclient {
	c.queryParams = queryParams
	return c
}

func (c *Httpclient) QueryParam(k, v string) *Httpclient {
	if c.queryParams == nil {
		c.queryParams = url.Values{}
	}

	c.queryParams[k] = []string{v}

	return c
}
func (c *Httpclient) Ctx(ctx context.Context) *Httpclient {
	c.ctx = ctx
	return c
}

func (c *Httpclient) Timeout(timeout time.Duration) *Httpclient {
	c.timeout = timeout
	return c
}

func (c *Httpclient) Headers(headers map[string]string) *Httpclient {
	if len(c.headers) > 0 {
		for k, v := range headers {
			c.headers[k] = v
		}
	} else {
		c.headers = headers
	}
	return c
}

func (c *Httpclient) Header(k, v string) *Httpclient {
	if c.headers == nil {
		c.headers = make(map[string]string)
	}

	c.headers[k] = v

	return c
}

func (c *Httpclient) Post() (*Resp, error) {
	c.method = "POST"
	return c.Do()
}
func (c *Httpclient) Get() (*Resp, error) {
	c.method = "GET"
	return c.Do()
}

func (c *Httpclient) Do() (*Resp, error) {
	if c.queryParams != nil {
		c.body = []byte(c.queryParams.Encode())
	}
	var req *http.Request
	var err error
	if c.ctx == nil {
		req, err = http.NewRequest(c.method, c.url, bytes.NewBuffer(c.body))
	} else {
		req, err = http.NewRequestWithContext(c.ctx, c.method, c.url, bytes.NewBuffer(c.body))
	}

	if err != nil {
		return nil, err
	}

	if c.timeout > 0 {
		client.Timeout = c.timeout
	}

	req.Header.Set("Content-Type", "application/json")
	if len(c.queryParams) > 0 {
		req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
	}

	if len(c.headers) > 0 {
		for k, v := range c.headers {
			req.Header.Set(k, v)
		}
	}

	r, err := client.Do(req)
	if err != nil {
		return nil, err
	}

	defer r.Body.Close()

	content, err := io.ReadAll(r.Body)
	if err != nil {
		return nil, err
	}

	return &Resp{StatusCode: r.StatusCode, Content: content}, nil
}

type Resp struct {
	StatusCode int
	Content    []byte
}
